/******************************************************************************* 
 * Copyright (C) 2012-2015 Microfountain Technology, Inc. All Rights Reserved. 
 * 
 * Unauthorized copying of this file, via any medium is strictly prohibited.   
 * Proprietary and confidential
 * 
 * Last Modified: 2015-9-17 20:13:19
 ******************************************************************************/
package cn.com.xy.sms.sdk.db.entity.pubinfo;

import java.util.HashMap;

import android.content.ContentValues;
import android.os.Process;
import cn.com.xy.sms.sdk.constant.Constant;
import cn.com.xy.sms.sdk.db.DBManager;
import cn.com.xy.sms.sdk.db.XyCursor;
import cn.com.xy.sms.sdk.db.base.BaseManager;
import cn.com.xy.sms.sdk.db.entity.NetQueryTimeManager;
import cn.com.xy.sms.sdk.db.entity.SysParamEntityManager;
import cn.com.xy.sms.sdk.dex.DexUtil;
import cn.com.xy.sms.sdk.log.LogManager;
import cn.com.xy.sms.sdk.net.NetUtil;
import cn.com.xy.sms.sdk.net.XyHttpRunnable;
import cn.com.xy.sms.sdk.service.pubInfo.PubInfoService;
import cn.com.xy.sms.sdk.util.KeyManager;
import cn.com.xy.sms.sdk.util.StringUtils;
import cn.com.xy.sms.util.ParseManager;

 
/* SDK-397 huangzhiqiang 20160524 start */
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;

import cn.com.xy.sms.sdk.Iservice.OnlineUpdateCycleConfigInterface;
import cn.com.xy.sms.sdk.db.entity.SmsParseRecorder;
 /* SDK-397 huangzhiqiang 20160524 end */

/*SDK-616 hewengao 20160912 start*/
import cn.com.xy.sms.sdk.threadpool.SmartSmsThreadPoolManager;
/*SDK-616 hewengao 20160912 end*/
/**
 * 号码签名数据管理
 * 
 * @author hewengao
 * 
 */
public class NumNameManager {

    // public static ExecutorService pool = Executors.newFixedThreadPool(1);

    public static final String PIX = ";&XY_PIX&;";// 退订指令的分割符号
    public static final String ID = "id";
    public static final String NUM = "num"; // 接收号码10086,10010,10000
    public static final String NAME = "name"; // 签名
    public static final String CNUM = "cnum"; // 中心号码;
    public static final String CMD = "cmd"; // 指令;
    public static final String MARK_TIME = "mark_time"; // 是否需要上传签名(0:不需要 1:需要)
    /* SDK-478 huangzhiqiang 20160628 start */
    public static final String EC = "ec"; // 行业编码
    public static final String MARK_EC = "mark_ec"; // 是否需要上传行业编码(0:不需要 1:需要)
    public static final String LAST_EC_TIME = "last_ec_time"; // 最后一个行业编码的识别时间，通过这个字段来摆放行业编码位置，最新的行业编码在最后
    /* SDK-478 huangzhiqiang 20160628 end */
    /* SDK-397 huangzhiqiang 20160526 start */
    public static final String MARK_CMD = "mark_cmd"; // 是否需要上传退订指令(0:不需要 1:需要)
    public static final String LAST_NAME_PUBID = "last_name_pubid"; // 最后一个签名的PUBID
    public static final String LAST_NAME_TIME = "last_name_time"; // 最后一个签名的识别时间，通过这个字段来摆放签名位置，最新的签名在最后
    public static final String LAST_CMD_TIME = "last_cmd_time"; // 最后一个退订指令的识别时间，通过这个字段来摆放退订指令位置，最新的退订指令在最后
    public static final String LAST_QUERY_TIME = "last_query_time"; // 最近一次签名查询时间
    
    public static final String RESET_PUBID = "ResetPubId"; // 需要重置pubId的标识
    /* SDK-397 huangzhiqiang 20160526 end */
    private static final String TABLE_NAME = "tb_num_name";
    public static final String DROP_TABLE = " DROP TABLE IF EXISTS " + TABLE_NAME;

    public static String getCreateTableSql() {
        /* SDK-397 huangzhiqiang 20160524 start */
        /* SDK-478 huangzhiqiang 20160628 start */
        return "CREATE TABLE  IF NOT EXISTS " + TABLE_NAME + " (" + ID + " INTEGER PRIMARY KEY, " + NUM
                + " TEXT NOT NULL UNIQUE, " + NAME + " TEXT NOT NULL," + CMD + " TEXT , " + EC + " TEXT , " + CNUM
                + " TEXT," + MARK_TIME + " LONG DEFAULT 0," + MARK_CMD + " INTEGER DEFAULT 0," + MARK_EC
                + " INTEGER DEFAULT 0," + LAST_NAME_TIME + " INTEGER DEFAULT 0," + LAST_NAME_PUBID
                + " INTEGER DEFAULT 0," + LAST_CMD_TIME + " INTEGER DEFAULT 0," + LAST_EC_TIME + " INTEGER DEFAULT 0,"
                + LAST_QUERY_TIME + " INTEGER DEFAULT 0)";
        
        /* SDK-478 huangzhiqiang 20160628 end */
        /* SDK-397 huangzhiqiang 20160524 end */
    }

    public static final String ADD_CNUM = "ALTER TABLE " + TABLE_NAME + " ADD COLUMN " + CNUM + " TEXT ";
    public static final String ADD_MARK_TIME = "ALTER TABLE " + TABLE_NAME + " ADD COLUMN " + MARK_TIME
            + " LONG DEFAULT 0";
    public static final String ADD_CMD = "ALTER TABLE " + TABLE_NAME + " ADD COLUMN " + CMD + " TEXT ";
    /* SDK-397 huangzhiqiang 20160524 start */
    public static final String ADD_MARK_CMD = "ALTER TABLE " + TABLE_NAME + " ADD COLUMN " + MARK_CMD
            + " INTEGER DEFAULT 0";
    public static final String ADD_LAST_NAME_PUBID = "ALTER TABLE " + TABLE_NAME + " ADD COLUMN " + LAST_NAME_PUBID
            + " INTEGER DEFAULT 0";
    public static final String ADD_LAST_NAME_TIME = "ALTER TABLE " + TABLE_NAME + " ADD COLUMN " + LAST_NAME_TIME
            + " INTEGER DEFAULT 0";
    public static final String ADD_LAST_CMD_TIME = "ALTER TABLE " + TABLE_NAME + " ADD COLUMN " + LAST_CMD_TIME
            + " INTEGER DEFAULT 0";
    public static final String ADD_LAST_QUERY_TIME = "ALTER TABLE " + TABLE_NAME + " ADD COLUMN " + LAST_QUERY_TIME
            + " INTEGER DEFAULT 0";
    /* SDK-397 huangzhiqiang 20160524 start */
    /* SDK-478 huangzhiqiang 20160628 start */
    public static final String ADD_EC = "ALTER TABLE " + TABLE_NAME + " ADD COLUMN " + EC + " TEXT ";
    public static final String ADD_MARK_EC = "ALTER TABLE " + TABLE_NAME + " ADD COLUMN " + MARK_EC
            + " INTEGER DEFAULT 0";
    public static final String ADD_LAST_EC_TIME = "ALTER TABLE " + TABLE_NAME + " ADD COLUMN " + LAST_EC_TIME
            + " INTEGER DEFAULT 0";
    /* SDK-478 huangzhiqiang 20160628 end */

    /**
     * 根据号码获取对应企业签名信息
     * 
     * @param num
     * @param needUpload 是否只获取需要上报的签名数据 true:是 false:否
     * @return
     */
    private static String getNameByNum(String num, boolean needUpload) {
        if (StringUtils.isNull(num)) {
            return "";
        }
        return getFieldValue(NAME, needUpload ? (" num = ? AND " + MARK_TIME + " = 1 ") : " num = ? ",
                new String[] { num });
    }

    /* SDK-397 huangzhiqiang 20160524 start */
    /**
     * 根据号码获取对应退订指令信息
     * 
     * @param num
     * @param needUpload 是否只获取需要上报的退订指令数据 true:是 false:否
     * @return
     */
    public static String getCmdByNum(String num, boolean needUpload) {
        if (StringUtils.isNull(num)) {
            return "";
        }
        return getFieldValue(CMD, needUpload ? (" num = ? AND " + MARK_CMD + " = 1 ") : " num = ? ",
                new String[] { num });
    }

    /**
     * 根据号码获取指定字段数据
     * 
     * @param num
     * @param fieldName
     * @param whereClause
     * @param whereArgs
     * @return
     */
    private static String getFieldValue(String fieldName, String whereClause, String[] whereArgs) {
        if (StringUtils.isNull(fieldName)) {
            return "";
        }
        XyCursor cursor = null;
        try {
            cursor = DBManager.query(TABLE_NAME, new String[] { fieldName }, whereClause, whereArgs);
            if (cursor != null && cursor.moveToFirst()) {
                return cursor.getString(0);
            }
        } catch (Throwable e) {
            /*SDK-550 hewengao 20160719 start*/
            LogManager.w(Constant.TAG, "NumNameManager getDataByNum: ", e);
            /*SDK-550 hewengao 20160719 end*/
        } finally {
            XyCursor.closeCursor(cursor, true);
        }
        return "";
    }
    /* SDK-397 huangzhiqiang 20160524 end */

    /**
     * 是否存在签名上报权限
     * 
     * @return true:是 false:否
     */
    public static boolean numNamePower() {
        String[] str = { "HUAWEICARD" };
        boolean power = true;
        for (String c : str) {
            if (c.equals(XyHttpRunnable.appKey)) {
                power = false;
                break;
            }
        }
        power = SysParamEntityManager.getBooleanParam(Constant.getContext(), "num_name_power", power);
        return power;
    }

    /**
     * 解析企业名称及行业编码
     * 
     * @param paramsMap
     */
    public static void parseNumNameAndEcForMsg(HashMap<String, String> paramsMap) {
        try {
            String num = paramsMap.get("num");
            num = StringUtils.getPhoneNumberNo86(num);
            String msg = paramsMap.get("msg");
            String cnum = paramsMap.get("cnum");
            /* SDK-397 huangzhiqiang 20160526 start */
            long smsTime = Long.parseLong(paramsMap.get("smsTime"));
            /* SDK-478 huangzhiqiang 20160623 start */
            String[] corpAndEcArr = DexUtil.getCorpAndEc(msg);
            String name = corpAndEcArr[0];
            String industryCode = corpAndEcArr[1];
            saveOrUpdateNameInfo(num, name, cnum, 1, smsTime);
            saveOrUpdateECInfo(num, industryCode, cnum, 1, smsTime);
            /* SDK-478 huangzhiqiang 20160623 end */
            /* SDK-397 huangzhiqiang 20160526 end */

            queryPubInfoIfNeed(num, smsTime);
        } catch (Throwable e) {
            /*SDK-550 hewengao 20160719 start*/
            LogManager.w(Constant.TAG, "NumNameManager parseNumNameForMsg: ", e);
            /*SDK-550 hewengao 20160719 end*/
        }
    }

    /* SDK-478 huangzhiqiang 20160623 start */
    private static long saveOrUpdateNameInfo(String num, String name, String cnum, int markName,
            long smsTime) {
        if (StringUtils.isNull(num) || StringUtils.isNull(name)) {
            return -1;
        }
        try {
            NumName numInfo = queryDataByNum(num, false);
            if (numInfo != null) {
                String[] values = handleNewValue(numInfo.name, numInfo.lastNameTime, name, smsTime, ";");
                if (values == null) {
                    return -1;
                }
                String processedName = values[0]; // 解析后得到的签名数据
                String lastNameTime = values[1]; // 解析后得到的签名数据识别时间
                String lastQueryTime = String.valueOf(numInfo.lastQueryTime);
                String lastNamePubId = String.valueOf(numInfo.lastNamePubId);

                // 签名数据发生改变，重置最后查询时间为0，以便能进行签名是否更新对比
                if (!StringUtils.isNull(processedName) && !processedName.equals(numInfo.name)) {
                    lastQueryTime = "0";
                }
                // 最新签名已改变，将最新签名的pubId设置为-1，代表需要更新签名企业信息
                if (values.length == 3 && RESET_PUBID.equals(values[2])) {
                    lastNamePubId = "-1";
                }

                String[] contentValues = new String[] { NAME, processedName, LAST_NAME_TIME, lastNameTime,
                        LAST_QUERY_TIME, lastQueryTime, LAST_NAME_PUBID, lastNamePubId, CNUM, cnum, MARK_TIME,
                        String.valueOf(markName) };
                return updateByNum(num, contentValues);
            }

            /* SDK-614 huangzhiqiang 20160912 start */
            // 首次识别到签名，删除该号码的网络查询记录，以便在只使用号码查不到公众号数据的情况下能够带上签名再次查询公众号数据
            NetQueryTimeManager.delNetQueryNum(num, null);
            /* SDK-614 huangzhiqiang 20160912 end */
            return insert(NUM, num, NAME, name, LAST_NAME_TIME, String.valueOf(smsTime), CNUM, cnum, MARK_TIME,
                    String.valueOf(markName), LAST_NAME_PUBID, "-1");
        } catch (Throwable e) {
            /*SDK-550 hewengao 20160719 start*/
            LogManager.w(Constant.TAG, "NumNameManager saveOrUpdateNameInfo: ", e);
            /*SDK-550 hewengao 20160719 end*/
        }
        return -1;
    }

    /**
     * 新增/更新号码行业编码信息
     * 
     * @param num 号码
     * @param ec 行业编码
     * @param cnum 短信中心号码
     * @param markEC 是否需要上传行业编码(0:不需要   1:需要)
     * @param smsTime 短信接收时间
     * @return
     */
    private static boolean saveOrUpdateECInfo(String num, String ec, String cnum, int markEC, long smsTime) {
        if (!StringUtils.allValuesIsNotNull(num, ec)) {
            return false;
        }
        return saveOrUpdateNumInfo(num, cnum, EC, ec, MARK_EC, "1", LAST_EC_TIME, smsTime, ";");
    }
    /* SDK-478 huangzhiqiang 20160623 end */

    private static void queryPubInfoIfNeed(final String num, long smsTime) {
        long time = System.currentTimeMillis() - smsTime;
        if (time >= 0 && time < Constant.MINUTE) {
            // 新收到的短信，小于1分钟，查询企业资料。
            /*SDK-616 hewengao 20160912 start*/
//            SmartSmsThreadPoolManager.pool;
            SmartSmsThreadPoolManager.pubInfoPool.execute(new Runnable() {
            /*SDK-616 hewengao 20160912 end*/
                @Override
                public void run() {
                    try {
                        /*SDK-633 hewengao 20161009 start*/
                        SmartSmsThreadPoolManager.setThreadNameAndPriority(SmartSmsThreadPoolManager.TNAME_QUERY_PUBINFO, Process.THREAD_PRIORITY_BACKGROUND);
                        /*SDK-633 hewengao 20161009 end*/
                        HashMap<String, String> extend = new HashMap<String, String>();
                        extend.put("SUPPORT_NET_QUERY", "1");
                        PubInfoService.queryPublicInfo(Constant.getContext(), num, 1, null, extend, null);
                    } catch (Throwable e) {
                        /*SDK-550 hewengao 20160719 start*/
                        LogManager.e(Constant.TAG, "NumNameManager queryPubInfoIfNeed error:", e);
                        /*SDK-550 hewengao 20160719 end*/
                    }
                }
            });
        }
    }

    /**
     * 解析退订指令
     * 
     * @param paramsMap
     */
    public static void parseCmdForMsg(HashMap<String, String> paramsMap) {
        try {
            String num = paramsMap.get("num");
            num = StringUtils.getPhoneNumberNo86(num);
            String msg = paramsMap.get("msg");
            /* SDK-395 huangzhiqiang 20160418 start */
            String retTDCmd = DexUtil.getCmd(num, msg);
            if (StringUtils.isNull(retTDCmd)) {
                return;
            }
            String cnum = paramsMap.get("cnum");
            /* SDK-397 huangzhiqiang 20160526 start */
            long smsTime = Long.parseLong(paramsMap.get("smsTime"));
            /* SDK-478 huangzhiqiang 20160623 start */
            saveOrUpdateCmdInfo(num, retTDCmd.trim(), cnum, 1, smsTime);
            /* SDK-478 huangzhiqiang 20160623 end */
            /* SDK-397 huangzhiqiang 20160526 end */
            /* SDK-395 huangzhiqiang 20160418 end */
        } catch (Exception e) {
            /*SDK-550 hewengao 20160719 start*/
            LogManager.w(Constant.TAG, "NumNameManager parseCmdForMsg: ", e);
            /*SDK-550 hewengao 20160719 start*/
        }
    }

    /* SDK-478 huangzhiqiang 20160623 start */
    /**
     * 新增/更新号码退订指令信息
     * 
     * @param num 号码
     * @param cmd 退订指令
     * @param cnum 短信中心号码
     * @param markCmd 是否需要上传退订指令(0:不需要   1:需要)
     * @param smsTime 短信接收时间
     * @return
     */
    private static boolean saveOrUpdateCmdInfo(String num, String cmd, String cnum, int markCmd, long smsTime) {
        if (!StringUtils.allValuesIsNotNull(num, cmd)) {
            return false;
        }
        return saveOrUpdateNumInfo(num, cnum, CMD, cmd, MARK_CMD, String.valueOf(markCmd), LAST_CMD_TIME, smsTime, PIX);
    }

    /**
     * 新增/更新号码信息
     * 
     * @param num 公众号号码
     * @param cnum 短信中心号码
     * @param fieldName 退订指令或行业编码字段名(cmd or ec)
     * @param fieldValue 退订指令或行业编码字段值
     * @param markFieldName 退订指令或行业编码的上传标志字段(mark_cmd or mark_ec)
     * @param markValue 上传标志字段值("1" or "0")，1代表需要上传，0代表不需要上传
     * @param lastTimeFieldName 退订指令或行业编码的识别时间字段(last_cmd_time or last_ec_time)
     * @param msgTime 短信接收时间
     * @param split 数据拆分符
     */
    private static boolean saveOrUpdateNumInfo(String num, String cnum, String fieldName, String fieldValue,
            String markFieldName, String markValue, String lastTimeFieldName, long msgTime, String split) {
        if (!StringUtils.allValuesIsNotNull(num, fieldName, fieldValue, markFieldName, markValue, lastTimeFieldName,
                split)) {
            return false;
        }
        try {
            NumName numInfo = queryDataByNum(num, false);
            if (numInfo != null) {
                String originalValue = null;
                long originalTime = 0;
                if (CMD.equals(fieldName)) {
                    originalValue = numInfo.cmd;
                    originalTime = numInfo.lastCmdTime;
                } else {
                    originalValue = numInfo.ec;
                    originalTime = numInfo.lastECTime;
                }
                String[] values = handleNewValue(originalValue, originalTime, fieldValue, msgTime, split);
                if (values == null) {
                    return false;
                }
                String processedValue = values[0]; // 解析后得到的数据
                String lastTime = values[1]; // 解析后得到的识别时间
                String[] contentValues = new String[] { fieldName, processedValue, lastTimeFieldName, lastTime, CNUM,
                        cnum, markFieldName, markValue };
                return updateByNum(num, contentValues) > 0;
            }

            /* SDK-577 huangzhiqiang 20160804 start */
            return insert(NUM, num, fieldName, fieldValue, CNUM, cnum, markFieldName, markValue, lastTimeFieldName,
                    String.valueOf(msgTime), NAME, "") > 0;
            /* SDK-577 huangzhiqiang 20160804 end */
        } catch (Throwable e) {
            /*SDK-550 hewengao 20160719 start*/
            LogManager.w(Constant.TAG, "NumNameManager saveOrUpdateNumInfo: ", e);
            /*SDK-550 hewengao 20160719 end*/
        }
        return false;
    }
    /* SDK-478 huangzhiqiang 20160623 end */

    /* SDK-397 huangzhiqiang 20160526 start */
    /**
     * 根据短信时间判断是否需要添加新数据，如果需要则根据条件将新数据加到原数据结尾或开头
     * 
     * @param originalValue 原有数据
     * @param originalTime 原最后一个数据的识别时间
     * @param data 当前数据
     * @param msgTime 短信接收时间
     * @param split 拆分符
     * @return index0:最终要入库的数据 index1:识别时间 index2:上传标志(1代表需要上传，0代表不需要上传)
     */
    private static String[] handleNewValue(String originalValue, long originalTime, String data, long msgTime,
            String split) {
        // 原有数据为空，直接返回当前数据
        if (StringUtils.isNull(originalValue)) {
            return new String[] { data, String.valueOf(msgTime) };
        }

        // 当前数据为空，直接返回原数据
        if (StringUtils.isNull(data)) {
            return new String[] { originalValue, String.valueOf(originalTime) };
        }

        // 当前数据与原有数据相同只是时间不同，返回当前数据
        if (data.equals(originalValue) && msgTime != originalTime) {
            return new String[] { data, String.valueOf(msgTime) };
        }

        List<String> allDatas = Arrays.asList(originalValue.split(split));
        int dataSize = allDatas.size();
        boolean isNewData = msgTime >= originalTime;
        boolean canAppendNewData = dataSize < 5;

        // 1当前数据不是最新数据并且库里已经存在5个数据就不再进行更新， 因为最新的短信总是先识别，所以库里这5个数据已经是最新的
        // 2当前数据不是最新的并且库里已经存在该数据，不需要进行更新
        if (!isNewData && (!canAppendNewData || allDatas.contains(data))) {
            return null;
        }

        // 最新数据已在结尾时的处理
        if (isNewData && data.equals(allDatas.get(dataSize - 1))) {
            if (msgTime != originalTime) {
                // 最新的数据已经在数据结尾了，只需要更新最新识别时间
                return new String[] { originalValue, String.valueOf(msgTime) };
            } else {
                // 最新的数据已经在数据结尾并且短信时间一致则不需要进更新
                return null;
            }
        }

        // 库里未满5个数据或当前数据是新的
        String[] result = null;
        if (isNewData) {
            boolean dbExistsThisData = allDatas.contains(data);
            if (canAppendNewData || dbExistsThisData) {
                String newDate = originalValue;
                // 库里已经有该数据
                if (dbExistsThisData) {
                    // 去除原数据里相同的数据
                    newDate = getExcludeDataValue(allDatas, data, split);
                }
                // 当前数据是最新的且库还有位置存放该数据，把该数据放在最后
                result = new String[] { (newDate + split + data), String.valueOf(msgTime), RESET_PUBID };
            } else {
                // 当前数据是最新的且库里已有5个其它数据，丢弃那5个旧数据，直接使用当前数据
                result = new String[] { data, String.valueOf(msgTime), RESET_PUBID };
            }
        } else {
            // 当前数据不是最新的且库还有位置存放该数据，添加到原数据前面
            result = new String[] { (data + split + originalValue), String.valueOf(originalTime) };
        }
        return result;
    }

    /**
     * 排除掉数据集合中的指定数据
     * 
     * @param allDatas 数据集合
     * @param excludeData 需要排除的数据
     * @param split 数据间的拆分符号
     * @return
     */
    private static String getExcludeDataValue(List<String> allDatas, String excludeData, String split) {
        if (allDatas == null || StringUtils.isNull(excludeData)) {
            return "";
        }
        int dataSize = allDatas.size();
        StringBuilder sbrValues = new StringBuilder();
        for (int i = 0; i < dataSize; i++) {
            String value = allDatas.get(i);
            if (!value.equals(excludeData)) {
                if (sbrValues.length() > 0 && !StringUtils.isNull(split)) {
                    sbrValues.append(split);
                }
                sbrValues.append(value);
            }
        }
        return sbrValues.toString();
    }

    /**
     * 新增号码数据
     * 
     * @param args
     * @throws Exception
     */
    private static long insert(String... args) throws Exception {
        return DBManager.insert(TABLE_NAME, BaseManager.getContentValues(null, args));
    }

    /**
     * 更新号码数据
     * 
     * @param num
     * @param args
     * @throws Exception
     */
    private static long updateByNum(String num, String... args) throws Exception {
        return DBManager.update(TABLE_NAME, BaseManager.getContentValues(null, args), NUM + " = ? ", new String[] { num });
    }
    /* SDK-397 huangzhiqiang 20160526 end */

    /**
     * 异步查询企业资料
     * 
     * @param paramsMap
     */
    public static void queryPublicInfoAsynchronous(final HashMap<String, String> paramsMap) {
        try {
            if (!"SAMCLASSFIYVwIDAQAB".equals(KeyManager.channel))
                return;
            /*SDK-616 hewengao 20160912 start*/
//            SmartSmsThreadPoolManager.pool;
            SmartSmsThreadPoolManager.pubInfoPool.execute(new Runnable() {
            /*SDK-616 hewengao 20160912 end*/
                @Override
                public void run() {
                    try {
                        /*SDK-633 hewengao 20161009 start*/
                        SmartSmsThreadPoolManager.setThreadNameAndPriority(SmartSmsThreadPoolManager.TNAME_QUERY_PUBINFO, Process.THREAD_PRIORITY_BACKGROUND);
                        /*SDK-633 hewengao 20161009 end*/
                        ParseManager.queryPublicInfo(Constant.getContext(), paramsMap.get("num"), 1, "", null, null);
                    } catch (Throwable e) {
                        /*SDK-550 hewengao 20160719 start*/
                        LogManager.w(Constant.TAG, e.getMessage(), e);
                        /*SDK-550 hewengao 20160719 end*/
                    }
                }
            });
        } catch (Throwable e) {
            /*SDK-550 hewengao 20160719 start*/
            LogManager.w(Constant.TAG, "NumNameManager queryPublicInfoAsynchronous: ", e);
            /*SDK-550 hewengao 20160719 end*/
        }
    }

    /**
     * 根据号码获取需要上传的号码数据(带权限检查)
     * 
     * @param num
     * @return
     */
    public static NumName getNumNameByNum(String num) {
        if (!numNamePower()) {
            return null;
        }
        return queryDataByNum(num, true);
    }

    /* SDK-423 huangzhiqiang 20160524 start */
    /**
     * 根据查询条件获取数据
     * 
     * @param whereClause
     * @param whereArgs
     * @param limit
     * @return
     */
    public static List<NumName> query(String whereClause, String[] whereArgs, int limit) {
        if (limit < 1) {
            return null;
        }

        XyCursor cursor = null;
        try {
            /* SDK-397 huangzhiqiang 20160526 start */
            cursor = DBManager.query(TABLE_NAME,
                    new String[] { ID, NUM, NAME, CMD, EC, CNUM, MARK_TIME, MARK_CMD, MARK_EC, LAST_NAME_PUBID, LAST_NAME_TIME,
                            LAST_CMD_TIME, LAST_EC_TIME, LAST_QUERY_TIME },
                    whereClause, whereArgs, null, null, null, String.valueOf(limit));
            /* SDK-397 huangzhiqiang 20160526 end */
            if (cursor == null || cursor.getCount() < 1) {
                return null;
            }
            List<NumName> numNames = new ArrayList<NumName>();
            NumName numName = null;
            while (cursor.moveToNext()) {
                numName = new NumName();
                numName.id = cursor.getInt(cursor.getColumnIndex(ID));
                numName.num = cursor.getString(cursor.getColumnIndex(NUM));
                numName.name = cursor.getString(cursor.getColumnIndex(NAME));
                numName.cmd = cursor.getString(cursor.getColumnIndex(CMD));
                numName.cnum = cursor.getString(cursor.getColumnIndex(CNUM));
                numName.markTime = cursor.getLong(cursor.getColumnIndex(MARK_TIME));
                numName.markCmd = cursor.getInt(cursor.getColumnIndex(MARK_CMD));
                /* SDK-397 huangzhiqiang 20160526 start */
                numName.lastNamePubId = cursor.getInt(cursor.getColumnIndex(LAST_NAME_PUBID));
                numName.lastNameTime = cursor.getLong(cursor.getColumnIndex(LAST_NAME_TIME));
                numName.lastCmdTime = cursor.getLong(cursor.getColumnIndex(LAST_CMD_TIME));
                /* SDK-397 huangzhiqiang 20160526 end */
                numName.lastQueryTime = cursor.getLong(cursor.getColumnIndex(LAST_QUERY_TIME));
                /* SDK-478 huangzhiqiang 20160628 start */
                numName.ec = cursor.getString(cursor.getColumnIndex(EC));
                numName.markEC = cursor.getInt(cursor.getColumnIndex(MARK_EC));
                numName.lastECTime = cursor.getLong(cursor.getColumnIndex(LAST_EC_TIME));
                /* SDK-478 huangzhiqiang 20160628 end */
                numNames.add(numName);
            }
            return numNames;
        } catch (Throwable e) {
            /*SDK-550 hewengao 20160719 start*/
            LogManager.w(Constant.TAG, "NumNameManager query: ", e);
            /*SDK-550 hewengao 20160719 end*/
        } finally {
            XyCursor.closeCursor(cursor, true);
        }
        return null;
    }

    /**
     * 查询一批号码对应的应企业签名信息(带权限检查)
     * 
     * @param num
     * @return
     */
    public static List<NumName> querySignInfoByNums(List<String> nums) {
        if (!numNamePower()) {
            return null;
        }
        return queryDataByNums(nums, null);
    }

    /**
     * 查询一批号码对应的数据
     * 
     * @param nums
     * @param extraWhereClause 额外的查询条件
     * @return
     */
    public static List<NumName> queryDataByNums(List<String> nums, String extraWhereClause) {
        if (nums == null || nums.size() < 1) {
            return null;
        }
        int size = nums.size();
        StringBuffer whereClause = new StringBuffer(NUM);
        whereClause.append(" IN(");
        whereClause.append(SmsParseRecorder.makePlaceholders(size));
        whereClause.append(")");
        if (!StringUtils.isNull(extraWhereClause)) {
            whereClause.append(extraWhereClause);
        }
        String[] whereArgs = nums.toArray(new String[size]);
        return query(whereClause.toString(), whereArgs, Integer.MAX_VALUE);
    }
    /* SDK-423 huangzhiqiang 20160524 end */

    /**
     * 根据号码查询号码对应数据
     * 
     * @param num
     * @param needUpload 获取需要上报的签名或退订指令 true:只获取需要上报的数据 false:获取所有数据
     * @return
     */
    public static NumName queryDataByNum(String num, boolean needUpload) {
        XyCursor cursor = null;
        try {
            StringBuffer whereClause = new StringBuffer(NUM);
            whereClause.append(" = ? ");
            /* SDK-397 huangzhiqiang 20160524 start */
            if (needUpload) {
                whereClause.append(" AND (");
                whereClause.append(MARK_TIME);
                whereClause.append(" = 1 OR ");
                whereClause.append(MARK_CMD);
                /* SDK-478 huangzhiqiang 20160628 start */
                whereClause.append(" = 1 OR ");
                whereClause.append(MARK_EC);
                whereClause.append(" = 1) ");
                /* SDK-478 huangzhiqiang 20160628 end */
            }

            List<NumName> numNames = query(whereClause.toString(), new String[] { num }, 1);
            if (numNames == null || numNames.size() < 1) {
                return null;
            }
            return numNames.get(0);
            /* SDK-397 huangzhiqiang 20160524 end */
        } catch (Throwable e) {
            /*SDK-550 hewengao 20160719 start*/
            LogManager.w(Constant.TAG, "NumNameManager queryDataByNum: ", e);
            /*SDK-550 hewengao 20160719 end*/
        } finally {
            XyCursor.closeCursor(cursor, true);
        }
        return null;
    }

    /* SDK-397 huangzhiqiang 20160526 start */
    /**
     * 获取指定号码的最新号码签名
     * 
     * @param num 号码
     * @return
     */
    public static String getLatestNumName(String num) {
        String allNumName = getNameByNum(num, false);
        if (StringUtils.isNull(allNumName)) {
            return null;
        }
        // 号码签名格式:签名1;签名2;签名3
        // 排在最后的为最新的号码签名，即签名3为最新的
        return getLastString(allNumName.split(";"));
    }

    /**
     * 获取指定号码的最新号码签名
     * 
     * @param numName 签名数据对象
     * @return
     */
    public static String getLatestNumName(NumName numName) {
        if (numName == null || StringUtils.isNull(numName.name)) {
            return null;
        }

        // 号码签名格式:签名1;签名2;签名3
        // 排在最后的为最新的号码签名，即签名3为最新的
        return getLastString(numName.name.split(";"));
    }

    /**
     * 获取字符串数据中排在结尾索引的字符串
     * 
     * @param arr
     * @return
     */
    public static String getLastString(String[] arr) {
        if (arr == null || arr.length == 0) {
            return null;
        }
        return arr[arr.length - 1];
    }

    /**
     * 能够进行签名查询（防止重复向服务器发送请求，相同号码请求间隔为1天）
     * 
     * @param lastQueryTime
     * @return
     */
    public static boolean canQuerySignInfo(long lastQueryTime) {
        return (System.currentTimeMillis() - lastQueryTime) > DexUtil
                .getUpdateCycleByType(OnlineUpdateCycleConfigInterface.TYPE_SIGN_QUERY_CYCLE, Constant.DAY);
    }

    /**
     * 根据号码更新上传标志
     * 
     * @param num
     * @param markValue 上传标志(0:不需要上传 1:需要上传)
     * @param updateType 更新类型（0:更新签名及退订指令上传标志 1:只更新签名上传标志 2:只更新退订指令上传标志）
     */
    public static void updateMarkByNum(String num, int markValue, int updateType) {
        if (StringUtils.isNull(num)) {
            return;
        }
        updateMarkByNum(markValue, NUM + " = ?", new String[] { num }, updateType);
    }

    /**
     * 根据号码更新上传标志，批量
     * 
     * @param numList
     * @param markValue 上传标志(0:不需要上传 1:需要上传)
     * @param updateType 更新类型（
     *                       0:同时更新签名、退订指令、行业编码上传标志 
     *                       1:只更新签名上传标志 
     *                       2:只更新退订指令上传标志
     *                       3:只更新行业编码上传标志）
     */
    public static void updateMarkByNum(List<String> numList, int markValue, int updateType) {
        if (numList == null || numList.isEmpty()) {
            return;
        }
        String placeholders = SmsParseRecorder.makePlaceholders(numList.size());
        String whereClause = NUM + " IN (" + placeholders + ")";
        String[] whereArgs = numList.toArray(new String[numList.size()]);
        updateMarkByNum(markValue, whereClause, whereArgs, updateType);
    }

    /**
     * 根据指定条件更新上传标志
     * 
     * @param markValue 上传标志(0:不需要上传 1:需要上传)
     * @param whereClause
     * @param whereArgs
     * @param updateType 更新类型（
     *                       0:同时更新签名、退订指令、行业编码上传标志 
     *                       1:只更新签名上传标志 
     *                       2:只更新退订指令上传标志
     *                       3:只更新行业编码上传标志）
     */
    private static void updateMarkByNum(int markValue, String whereClause, String[] whereArgs, int updateType) {
        boolean numNamePower = numNamePower();
        String markValueStr = String.valueOf(markValue);
        String[] args = null;
        switch (updateType) {
        case 1: // 只更新签名上传标志
            if (numNamePower) {
                args = new String[] { MARK_TIME, markValueStr };
            }
            break;
        case 2: // 只更新退订指令上传标志
            args = new String[] { MARK_CMD, markValueStr };
            break;
            /* SDK-478 huangzhiqiang 20160628 start */
        case 3: // 只更新行业编码上传标志
            args = new String[] { MARK_EC, markValueStr };
            break;
        default: // 更新签名及退订指令上传标志
            if (numNamePower) {
                // 存在上传签名权限时才更新上传签名标志
                args = new String[] { MARK_TIME, markValueStr, MARK_CMD, markValueStr, MARK_EC, markValueStr };
            } else {
                args = new String[] { MARK_CMD, markValueStr, MARK_EC, markValueStr };
            }
            /* SDK-478 huangzhiqiang 20160628 end */
            break;
        }
        if (args == null) {
            return;
        }
        updateNunNameInfo(whereClause, whereArgs, args);
    }

    /**
     * 更新号码的最新签名对应的pubId
     * 
     * @param num
     * @param pubId
     */
    public static void updateLastNamePubIdByNum(String num, int pubId) {
        updateNunNameInfo(NUM + " = ?", new String[] { num }, new String[] { LAST_NAME_PUBID, String.valueOf(pubId) });
    }

    /**
     * 更新号码的最后查询时间及签名上传标志
     * 
     * @param num
     * @param lastQueryTime 最后查询时间
     * @param markValue 上传标志(0:不需要上传 1:需要上传)
     */
    public static void updateLastQueryTimeAndMark(String num, long lastQueryTime, int markValue) {
        updateNunNameInfo(NUM + " = ?", new String[] { num },
                new String[] { LAST_QUERY_TIME, String.valueOf(lastQueryTime), MARK_TIME, String.valueOf(markValue) });
    }

    /**
     * 更新数据
     * 
     * @param whereClause
     * @param whereArgs
     * @param args 更新字段及字段值键值对
     */
    private static void updateNunNameInfo(String whereClause, String[] whereArgs, String... args) {
        try {
            if (args == null || args.length == 0) {
                return;
            }
            ContentValues contentValues = BaseManager.getContentValues(null, args);
            DBManager.update(TABLE_NAME, contentValues, whereClause, whereArgs);
        } catch (Throwable e) {
            /*SDK-550 hewengao 20160719 start*/
            LogManager.w(Constant.TAG, "NumNameManager updateNunNameInfo: ", e);
            /*SDK-550 hewengao 20160719 end*/
        }
    }
    /* SDK-397 huangzhiqiang 20160526 end */
}
